function createLuaClient() {
    var luaScriptName = jsCrawler.config.getLuaScriptName()
    // logger.info(luaScriptName)
    var taskKey = context.get(LUA_TASK_KEY)
    // logger.info(taskKey)
    var isIE11 = jsCrawler.config.isIE11()
    // logger.info(isIE11)

    var luaClient = new LuaClient(luaScriptName, taskKey, isIE11);
    jsCrawler.setLuaClient(luaClient)
    logger.info("任务：【 {} 】 jsCrawler绑定luaClient", context.get(LUA_TASK_KEY))
    var luaProcess = luaClient.getLuaProcess()
    logger.info("任务：【 {} 】 LuaX进程ID【 {} 】", context.get(LUA_TASK_KEY), luaProcess.getProcessId())

    var scriptContext = context.get("scriptContext");

    scriptContext.setAttribute("lp", jsCrawler.luaClient.getLuaProcess(), ENGINE_SCOPE);
    logger.info("任务【 {} 】 scriptContext【 {} 】 cralwer实例【 {} 】", context.get(LUA_TASK_KEY), scriptContext, jsCrawler);

    return luaClient;
}

function setProxyForLuaClient() {

    if (jsCrawler.config.isEnableLuaProxy()) {
        var proxyInfo = context.get(LUA_TASK_PROXY_INFO);
        if (proxyInfo.length == 2) {
            logger.info("任务：【 {} 】为LuaClient设置代理：{}:{}",  context.get(LUA_TASK_KEY), proxyInfo[0], proxyInfo[1]);
            set_proxy(proxyInfo[0], proxyInfo[1])
        } else {
            logger.info("任务：【 {} 】未能为LuaClient设置代理",  context.get(LUA_TASK_KEY));
        }
    } else {
        logger.info("任务：【 {} 】已禁用LuaClient设置代理",  context.get(LUA_TASK_KEY));
    }
}

function createLuaClientAndSetProxy() {

    createLuaClient();
    setProxyForLuaClient();
}

function setProxyForHttpClient() {
    if (jsCrawler.config.isEnableHttpProxy()) {
        var proxyInfo = context.get(LUA_TASK_PROXY_INFO);
        if (proxyInfo.length === 2) {
            logger.info("任务：【 {} 】为HttpClient设置代理：{}:{}",  context.get(LUA_TASK_KEY), proxyInfo[0], proxyInfo[1]);
            ProxyFetchUtil.setProxyInfo(proxyInfo);
        } else {
            logger.info("任务：【 {} 】未能为HttpClient设置代理",  context.get(LUA_TASK_KEY));
        }
    } else {
        logger.info("任务：【 {} 】已禁用HttpClient设置代理",  context.get(LUA_TASK_KEY));
    }

}

/**
 * 代理不为空或代理已验证为可用不需要重新获取代理
 * @returns {*|boolean}
 */
function needGetProxy(){
    return ObjectUtils.equals(context.get(LUA_TASK_PROXY_INFO), null) ||
        (context.get(LUA_TASK_PROXY_INFO).length === 2 && !context.get("proxyAvailable"))
}

/**
 * 初始化环境
 * 1、获取代理
 * 2、若启用luaClient 判断lua进程是否存在，若存在关闭之，重新创建lua进程并设置代理
 * 3、若启用httpClient 则为httpClient设置代理
 */
function initEnvironment(){
    logger.info("任务：【 {} 】初始化环境中...", context.get(LUA_TASK_KEY));
    if (needGetProxy()){

        getProxyInfo(context);
    }

    //需要LuaClient
    if (jsCrawler.config.isLuaClient()) {

        var scriptContext = context.get("scriptContext");

        if(needResetEnvironment()) {
            var lpDeclare = scriptContext.getAttribute("lp", ENGINE_SCOPE);
            if(lpDeclare){
                logger.info("任务：【 {} 】 关闭lua进程【 {} 】", context.get(LUA_TASK_KEY), lp.getProcessId())
                lp.Close();
            }
            createLuaClientAndSetProxy()

        } else {
            setProxyForLuaClient()
        }
    }

    if (jsCrawler.config.isHttpClient()) {
        setProxyForHttpClient();

    }
}

function _execute(javaFuncs, funcName) {

    if(funcName === 'doAuthenticate') {
        return doAuthenticate(javaFuncs)
    }

    if(javaFuncs[funcName]) {
        //logger.info("任务：【 {} 】 银行名称【 {} 】 调用方法【 {} 】",  context.get(LUA_TASK_KEY), context.get(LUA_TASK_BANK_NAME), javaFuncs[funcName])
        return javaFuncs[funcName]()
    } else {
        logger.info("任务：【 {} 】 调用的方法【 {} 】不存在", context.get(LUA_TASK_KEY), funcName)
        throw new BankException(BALO_99605_10, "函数【 " + funcName + " 】未定义")
    }
}

function waitImgCodeBySecondsByJs(bizContext,  waitSeconds, isPlatform,times) {
    var taskKey = bizContext.get(LUA_TASK_KEY);
    var imgCode = "";
    logger.info("任务：【 {} 】等待图片验证码中，最长等待时间【 {}s 】", bizContext.get(LUA_TASK_KEY), waitSeconds);
    var base64Image;
    if (bizContext.get(TASK_IMG_PATH) != null){
        logger.info("任务：【 {} 】图片验证码路径：{}", bizContext.get(LUA_TASK_KEY),  bizContext.get(TASK_IMG_PATH));
        base64Image = encodePic(bizContext.get(TASK_IMG_PATH));
    } else if(bizContext.get(TASK_IMG_BYTES) != null){
        base64Image = bytesToBase64(bizContext.get(TASK_IMG_BYTES));
    } else {
        logger.error("任务：【 {} 】未获取到图片验证码的base64码", bizContext.get(LUA_TASK_KEY));
        throw new BankException(BALO_99602_50, "未在上下文中设置图片验证码信息");
    }
    logger.info("任务：【 {} 】图片验证码base64码【 {} 】", bizContext.get(LUA_TASK_KEY), base64Image);

    var finalBase64Image = base64Image;
    if(DEV_LEVEL.equals(System.getProperty(PROFILE_PROPERTY))){
        logger.info("任务：【 {} 】开发环境手动打码", taskKey);
        var br = new BufferedReader(new InputStreamReader(System.in));
        imgCode = br.readLine();
    } else {
        if (isPlatform) {
            var url = PropertyManager.getRB("config","captcha_url");
            var header = new HashMap();
            header.put(CONTENT_TYPE_KEY,CONTENT_TYPE);
            var jsonObject = null;
            try {
                var base64Info = new HashMap();
                base64Info.put("base64Image", finalBase64Image);
                base64Info.put("regex",bizContext.get(TASK_IMG_REGEX));
                base64Info.put("way", bizContext.get(LUA_TASK_KEY));
                base64Info.put("times", times);
                base64Info.put("taskId", bizContext.get(LUA_TASK_KEY));
                jsonObject = RequestUtil.postJsonNoProxy(url, base64Info, header);
                var json = JSON.parseObject(jsonObject);
                if("200".equals(json.getString("status"))){
                    imgCode = json.getString("code");
                }else{
                    logger.error("任务：【 {} 】打码服务识别失败，结果：{}", bizContext.get(LUA_TASK_KEY), json);
                    // throw new BankException(BankConstants.BALO_99604_60,errorMsgMap.get(BALO_99604_60));
                    //return error 后重新获取验证码
                    return "error";
                }
            }catch(e){
                logger.error("任务：【 {} 】人工打码异常:打码服务不可用", bizContext.get(LUA_TASK_KEY), e);
                throw new BankException(BankConstants.BALO_99604_60, e);
            }
        } else {
            saveTaskStatusByInteractiveCode(bizContext, IMG_INTERACTIVE_CODE, finalBase64Image);
            var taskStatusFromClient = getTaskStatusFromClient(bizContext, waitSeconds);
            imgCode = taskStatusFromClient.getInteractiveCodeMsg();
            if(null == taskStatusFromClient || StringUtils.isBlank(imgCode)){
                logger.warn("任务：【 {} 】图片验证码超时", taskKey);
                throw new BankException(BALO_99602_55, errorMsgMap.get(BALO_99602_55));
            }
        }

    }
    logger.info("任务：【 {} 】接收到的图片验证码为【 {} 】", bizContext.get(LUA_TASK_KEY), imgCode);
    return imgCode;
}

function wait4ImgCodeBySeconds(bizContext,waitSeconds) {
    var imgCode = "";
    logger.info("任务：【 {} 】等待图片验证码中，最长等待时间【 {}s 】", bizContext.get(LUA_TASK_KEY), waitSeconds);
    var base64Image;
    if (bizContext.get(TASK_IMG_PATH) != null){
        logger.info("任务：【 {} 】图片验证码路径：{}", bizContext.get(LUA_TASK_KEY),  bizContext.get(TASK_IMG_PATH));
        base64Image = encodePic(bizContext.get(TASK_IMG_PATH));
    } else if(bizContext.get(TASK_IMG_BYTES) != null){
        base64Image = bytesToBase64(bizContext.get(TASK_IMG_BYTES));
    } else {
        logger.error("任务：【 {} 】未获取到图片验证码的base64码", bizContext.get(LUA_TASK_KEY));
        throw new BankException(BALO_99602_50, "未在上下文中设置图片验证码信息");
    }
    logger.info("任务：【 {} 】图片验证码base64码【 {} 】", bizContext.get(LUA_TASK_KEY), base64Image);

    var finalBase64Image = base64Image;
            var url = PropertyManager.getRB("config","captcha_url")+"/wait4platform";
            var header = new HashMap();
            header.put(CONTENT_TYPE_KEY,CONTENT_TYPE);
            var jsonObject = null;
            try {
                var base64Info = new HashMap();
                base64Info.put("base64Image", finalBase64Image);
                base64Info.put("way", bizContext.get(LUA_TASK_KEY));
                base64Info.put("taskId", bizContext.get(LUA_TASK_KEY));
                jsonObject = RequestUtil.postJsonNoProxy(url, base64Info, header);
                var json = JSON.parseObject(jsonObject);
                if("200".equals(json.getString("status"))){
                    imgCode = json.getString("code");
                }else if("401".equals(json.getString("status"))){
                    logger.error("任务：【 {} 】打码服务识别失败,所传Base64不是图片！", bizContext.get(LUA_TASK_KEY));
                    throw new BankException(BankConstants.BALO_99604_60, errorMsgMap.get(BALO_99604_60));
                }else{
                    logger.error("任务：【 {} 】打码服务识别失败，结果：{}", bizContext.get(LUA_TASK_KEY), json);
                    throw new BankException(BankConstants.BALO_99604_60, json);
                }
            }catch(e){
                logger.error("任务：【 {} 】人工打码异常:打码服务不可用", bizContext.get(LUA_TASK_KEY), e);
                throw new BankException(BankConstants.BALO_99604_60, e);
            }
    logger.info("任务：【 {} 】接收到的图片验证码为【 {} 】", bizContext.get(LUA_TASK_KEY), imgCode);
    return imgCode;
}

function classify(desc, amountMoney){
    var target = ""
    desc = desc.replaceAll("[^\\u4E00-\\u9FA5]", "")

    if(amountMoney == null) {
        amountMoney = BigDecimal.ZERO
    }

    if (amountMoney.compareTo(BigDecimal.ZERO) > 0) {
        target = desc + "正";
    } else if(amountMoney.compareTo(BigDecimal.ZERO) === 0) {
        target = desc + "零";
    } else {
        target = desc + "负";
    }
    return context.classify.classify(target)
}